Skip to content

fix: ship dual ESM/CJS output for Node16 consumers#373

Merged
shashi-stackone merged 4 commits into
mainfrom
fix/dual-cjs-esm-output
Jul 7, 2026
Merged

fix: ship dual ESM/CJS output for Node16 consumers#373
shashi-stackone merged 4 commits into
mainfrom
fix/dual-cjs-esm-output

Conversation

@shashi-stackone

@shashi-stackone shashi-stackone commented Jul 6, 2026

Copy link
Copy Markdown
Contributor
  • Build with format: ['esm', 'cjs'] so dist/ ships .cjs/.d.cts alongside .mjs/.d.mts; tsdown regenerates publishConfig.exports with matching require/import conditions (declarations resolve via sibling files, correct under Node16 resolution). Fixes the TS1479 error for TypeScript consumers using module/moduleResolution: node16 in CommonJS projects.
  • Add a regression test that packs the package as published, installs it into a throwaway Node16 consumer, and type-checks .cts/.mts consumers with tsc — it fails with the exact TS1479 from the issue if ESM-only output ever returns — plus require()/import() smoke tests. No new dependencies.
  • Set rootDir in tsconfig.json to fix a pre-existing TS2209 that made pnpm test exit non-zero.

Note: dual-format packages carry the standard dual-package hazard — a process mixing require() and import() of this package gets two class copies, so cross-boundary instanceof checks can fail; discriminate via err.name or statusCode in that situation.

Fixes #350


Summary by cubic

Ship dual ESM/CJS output so Node16 TypeScript consumers can use both import and require. Fixes TS1479 in CommonJS projects and resolves #350.

  • Bug Fixes

    • Build dist/ as ESM and CJS via tsdown, emitting .mjs/.d.mts and .cjs/.d.cts; set "main" to ./dist/index.cjs, "module" to ./dist/index.mjs, "types" to ./dist/index.d.cts, and add publishConfig.exports with require/import conditions.
    • Add a regression test that packs with pnpm --config.ignore-scripts=true pack, installs into a throwaway Node16 consumer, type-checks .cts/.mts with tsc, smoke-tests require()/import(), verifies publishConfig.exports["."], skips build-output checks when dist/ is missing, and uses fileURLToPath(new URL(..., import.meta.url)) instead of import.meta.dirname.
    • Set "rootDir" in tsconfig.json to fix a pre-existing TS2209.
  • Migration

    • If a process mixes require() and import() of @stackone/ai, avoid cross-boundary instanceof; prefer discriminators like err.name or statusCode.

Written for commit 53beb9a. Summary will update on new commits.

Review in cubic

Copilot AI review requested due to automatic review settings July 6, 2026 15:02
@shashi-stackone shashi-stackone requested a review from a team as a code owner July 6, 2026 15:02
@pkg-pr-new

pkg-pr-new Bot commented Jul 6, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/StackOneHQ/stackone-ai-node/@stackone/ai@373

commit: 53beb9a

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the build/publish setup to ship dual ESM+CJS artifacts (and corresponding declaration outputs) to improve TypeScript compatibility for consumers using module/moduleResolution: node16 in CommonJS projects, and adds a regression test that exercises the packed-as-published output.

Changes:

  • Build dist/ in both esm and cjs formats via tsdown to produce .mjs/.d.mts and .cjs/.d.cts outputs.
  • Adjust package entrypoints/exports to publish separate require and import conditions.
  • Add a Vitest regression test that pnpm packs the package, installs it into a temporary Node16-resolution TS consumer, and type-checks it.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.

File Description
tsdown.config.ts Switches tsdown output to dual ['esm', 'cjs'] formats.
tsconfig.json Sets rootDir to address a pre-existing TS2209 and keep test exits clean.
scripts/package-exports.test.ts Adds a pack-and-typecheck regression test for published exports/types behavior.
package.json Updates entrypoints (main, types) and publish-time conditional exports for CJS/ESM.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/package-exports.test.ts Outdated
Comment on lines +38 to +41
* Packing goes through `pnpm pack` because it applies the publishConfig
* overrides (exports/main/types), producing the same package.json a consumer
* gets from the registry. Lifecycle scripts are disabled: the prepack script
* runs a full build, which must not happen inside the test.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="scripts/package-exports.test.ts">

<violation number="1" location="scripts/package-exports.test.ts:39">
P3: The JSDoc mentions that `pnpm pack` applies publishConfig overrides for `exports/main/types`, but `publishConfig` in this project only defines `exports`. The `main` and `types` fields are top-level package.json entries, not publishConfig overrides. This makes the comment misleading about what actually changes in the packed tarball versus the source package.json — consider updating it to just reference `exports`.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread scripts/package-exports.test.ts Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Requires human review: Changes build output from ESM-only to dual ESM/CJS and updates package exports. Moderate impact on package distribution; requires human review to verify no edge cases.

Re-trigger cubic

@shashi-stackone shashi-stackone changed the title fix(build): ship dual ESM/CJS output for Node16 consumers fix: ship dual ESM/CJS output for Node16 consumers Jul 6, 2026
cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes Jul 6, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Auto-approved: Build configuration and test-only changes: dual ESM/CJS output, entry points, and a regression test. No source logic modified.

Re-trigger cubic

@shashi-stackone shashi-stackone changed the title fix: ship dual ESM/CJS output for Node16 consumers fix: ship dual ESM/CJS output for Node16 consumers Jul 6, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Auto-approved: Build configuration updates for dual ESM/CJS output with regression tests; no business logic changes.

Re-trigger cubic

@shashi-stackone shashi-stackone merged commit b1739b1 into main Jul 7, 2026
19 checks passed
@shashi-stackone shashi-stackone deleted the fix/dual-cjs-esm-output branch July 7, 2026 09:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ship dual CJS/ESM types for Node16 TypeScript compatibility

2 participants